from InfluxDB_setting.api.mysql_api import *
from InfluxDB_setting.api.judging_system_api import *
import threading
import time as time_module

# 存储异常结束后的跟踪任务
post_anomaly_tracking = {}
# 存储活跃异常
active_post_anomaly_tasks = {}


def track_post_anomaly_data(measurement, field, device, duration=10):
    """
    在异常结束后继续跟踪收集数据
    :param measurement: 测量类型
    :param field: 字段名
    :param device: 设备名
    :param duration: 跟踪持续时间（秒）
    """
    tracking_id = f"{device}_{measurement}_{field}"

    def tracking_task():
        end_time = time_module.time() + duration
        while time_module.time() < end_time:
            # 这里应该从InfluxDB获取最新数据
            # 为简化，我们只是记录需要继续收集数据的任务
            time_module.sleep(1)  # 每秒检查一次

        # 跟踪结束后清理
        if tracking_id in active_post_anomaly_tasks:
            del active_post_anomaly_tasks[tracking_id]
        print(f"异常后数据跟踪结束: {tracking_id}")

    # 记录跟踪任务
    active_post_anomaly_tasks[tracking_id] = {
        "end_time": time_module.time() + duration,
        "measurement": measurement,
        "field": field,
        "device": device
    }
    print(f"开始异常后数据跟踪: {tracking_id}，持续{duration}秒")


def collect_post_anomaly_data(measurement, field, local_time, value, device):
    """
    收集异常结束后的数据
    """
    # # 调用专门处理异常后数据收集的函数
    # post_anomaly_data_collection(measurement, field, local_time, value, device)


def main():
    global last_diskio_iotime, rules
    with InfluxDBClient(url=url, token=token, org=org) as client:
        last_time = (datetime.now(timezone.utc) - timedelta(minutes=1)).isoformat()
        last_batch_time = datetime.now(timezone.utc)  # 记录上次批量发送时间

        while True:
            records = query_new_data(client, bucket, org, last_time)
            if records:
                for record in records:
                    utc_time = record.get_time()
                    local_time = utc_time.astimezone(pytz.timezone("Asia/Shanghai"))
                    measurement = record.get_measurement()
                    field = record.get_field()
                    value = record.get_value()
                    tags = extract_tags(record)

                    device = tags.get("device") or tags.get("name") or "unknown"
                    interface = tags.get("interface", "unknown")
                    serial = tags.get("serial", "unknown")
                    irq = tags.get("irq", None)
                    fstype = tags.get("fstype", None)
                    mode = tags.get("mode", None)
                    path = tags.get("path", None)
                    label = tags.get("label", None)
                    prefix = ""
                    anomaly_detected = False
                    anomaly_id = None
                    threshold = None
                    log_message = ""

                    # 针对 diskio/io_time 做差分处理
                    if measurement == "diskio" and field == "io_time":
                        key = (measurement, field, device)
                        prev_value = last_diskio_iotime.get(key)

                        if prev_value is None:
                            last_diskio_iotime[key] = value
                            log_message = (f"Time: {local_time}, Measurement: {measurement}, Field: {field},"
                                           f" Device: {device}, Initial io_time value: {value} (no diff)")
                            print(log_message)
                        else:
                            diff = value - prev_value
                            if diff < 0:
                                diff = 0

                            measurement_rules = rules.get(measurement, {})
                            field_rule = measurement_rules.get(field)

                            if field_rule:
                                if isinstance(field_rule, list):
                                    for rule in field_rule:
                                        if is_abnormal(diff, rule.get("threshold"), rule.get("condition")):
                                            prefix = RED_EXCLAMATION
                                            anomaly_detected = True
                                            threshold = rule.get("threshold")
                                            break
                                else:
                                    if is_abnormal(diff, field_rule.get("threshold"), field_rule.get("condition")):
                                        prefix = RED_EXCLAMATION
                                        anomaly_detected = True
                                        threshold = field_rule.get("threshold")

                            log_message = f"{prefix}Time: {local_time}, Measurement: {measurement}, Field: {field}, Device: {device}, Real-time io_time increment: {diff}"
                            print(log_message)
                            last_diskio_iotime[key] = value
                    else:
                        # 其他字段直接判断异常
                        measurement_rules = rules.get(measurement, {})
                        field_rule = measurement_rules.get(field)

                        if field_rule:
                            if isinstance(field_rule, list):
                                for rule in field_rule:
                                    if is_abnormal(value, rule.get("threshold"), rule.get("condition")):
                                        prefix = RED_EXCLAMATION
                                        anomaly_detected = True
                                        threshold = rule.get("threshold")
                                        break
                            else:
                                if is_abnormal(value, field_rule.get("threshold"), field_rule.get("condition")):
                                    prefix = RED_EXCLAMATION
                                    anomaly_detected = True
                                    threshold = field_rule.get("threshold")

                        log_message = f"{prefix}Time: {local_time}, Measurement: {measurement}, Field: {field}, Value: {value}, Device: {device}, Interface: {interface}, Serial: {serial}, IRQ: {irq}, Fstype: {fstype}, Mode: {mode}, Path: {path}, Label: {label}"
                        print(log_message)

                    # 检查是否是活跃的异常后跟踪任务
                    tracking_id = f"{device}_{measurement}_{field}"
                    if tracking_id in active_post_anomaly_tasks:
                        # 收集异常结束后的数据
                        collect_post_anomaly_data(measurement, field, local_time, value, device)
                        # 检查是否已超过跟踪时间
                        if time_module.time() >= active_post_anomaly_tasks[tracking_id]["end_time"]:
                            del active_post_anomaly_tasks[tracking_id]
                            print(f"异常后数据收集完成: {tracking_id}")

                    # 如果检测到异常，更新异常状态
                    if anomaly_detected:
                        anomaly_id = create_anomaly_id(measurement, field, device)
                        update_anomaly_state(anomaly_id, measurement, field, value, threshold, device, tags,
                                             log_message)
                        # 启动异常后数据跟踪
                        if tracking_id not in active_post_anomaly_tasks:
                            track_post_anomaly_data(measurement, field, device, duration=10)

                    # # 只有在检测到异常或正在跟踪异常后数据时才存储数据
                    # if anomaly_detected or tracking_id in active_post_anomaly_tasks:
                    #     # mysql_api中实现（告警可视化图表+已修复报告）
                    #     insert_alert_data(measurement, field, local_time, value, device, is_anomaly=anomaly_detected)

                    # mysql_api中实现
                    insert_data(prefix, measurement, field, value, local_time, tags, serial, interface, device, path,
                                irq, fstype, mode, label)
                print("-" * 50)
                last_time = records[-1].get_time().isoformat()
            else:
                print("No new data.")
            send_batch_anomalies_to_llm()  # 调用批量发送函数
            cleanup_resolved_anomalies()  # 清理已解决异常
            time_module.sleep(10)  # 缩短为10秒


if __name__ == "__main__":
    main()
